//
// Created by webturing on 2024/5/4.
//
#include <bits/stdc++.h>

using namespace std;

constexpr int inf = 0x3f3f3f3f;

constexpr int szd = 4 * 3;

constexpr int maxn = 30 + 1;

constexpr int dirs[][2]{0, 1, 1, 0, 0, -1, -1, 0,
                        0, 2, 2, 0, 0, -2, -2, 0, -1, -1, -1, 1, 1, 1, 1, -1};

struct node {
    int r, c, w;

    node(int r, int c, int w) : r(r), c(c), w(w) {};

    bool operator<(const node &x) const {
        return w > x.w;
    }
};

int m, n;

vector<vector<string>> mat;

int memo[maxn][maxn][maxn];

int bfs(int level, int sr, int sc) {
    if ( memo[level][sr][sc] != -1 ) return memo[level][sr][sc];
    priority_queue<node> pq;
    pq.emplace(sr, sc, 0);
    vector<vector<int>> d(n, vector<int>(n, inf));
    d[sr][sc] = 0;
    int min_cost = inf;
    while (!pq.empty()) {
        auto [r, c, w] = pq.top();
        pq.pop();
        if ( d[r][c] < w ) continue;
        if ( mat[level][r][c] == 'E' ) return w;
        if ( mat[level][r][c] == 'U' )
            min_cost = min(min_cost, w + bfs(level + 1, r, c));
        for (int i = 0; i < szd; ++i) {
            int nr = r + dirs[i][0], nc = c + dirs[i][1];
            if ( nr < 0 or nr >= n or nc < 0 or nc >= n ) continue;
            if ( mat[level][nr][nc] == '#' ) continue;
            if ( i == 8 ) {
                if ( mat[level][r][c - 1] == '#' and mat[level][r - 1][c] == '#' ) continue;
            } else if ( i == 9 ) {
                if ( mat[level][r][c + 1] == '#' and mat[level][r - 1][c] == '#' ) continue;
            } else if ( i == 10 ) {
                if ( mat[level][r + 1][c] == '#' and mat[level][r][c + 1] == '#' ) continue;
            } else if ( i == 11 ) {
                if ( mat[level][r + 1][c] == '#' and mat[level][r][c - 1] == '#' ) continue;
            }
            int curr;
            if ( i < 4 or i >= 8 ) curr = 1;
            else if ( i < 8 ) {
                int tr = r + dirs[i - 4][0], tc = c + dirs[i - 4][1];
                if ( mat[level][tr][tc] == '#' ) curr = 3;
                else curr = 1;
            }
            if ( d[nr][nc] > d[r][c] + curr ) {
                d[nr][nc] = d[r][c] + curr;
                pq.emplace(nr, nc, d[nr][nc]);
            }
        }
    }
    return memo[level][sr][sc] = min_cost;
}

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    cin >> m >> n;
    mat = vector<vector<string>>(m, vector<string>(n));
    for (int i = 0; i < m; ++i)
        for (auto &s: mat[i])
            cin >> s;
    memset(memo, -1, sizeof memo);
    auto find = [&]() -> pair<int, int> {
        for (int r = 0; r < n; ++r)
            for (int c = 0; c < n; ++c)
                if ( mat[0][r][c] == 'S' ) return {r, c};
        return {0, 0};
    };
    auto [sr, sc] = find();
    int cost = bfs(0, sr, sc);
    if ( cost != inf ) cout << cost << '\n';
    else cout << "No" << '\n';
    return 0;
}
